home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / attach.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  15KB  |  657 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_menu.h"
  21. #include "mutt_curses.h"
  22. #include "keymap.h"
  23. #include "send.h"           /* for mutt_edit_file(), in curs_lib.c? */
  24. #include "rfc1524.h"
  25. #include "mime.h"
  26. #include "state.h"
  27. #include "parse.h"
  28.  
  29. #include <ctype.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <sys/wait.h>
  33. #include <sys/stat.h>
  34. #include <string.h>
  35. #include <errno.h>
  36.  
  37. /* 
  38.  * Currently, this only works for send mode, as it assumes that the 
  39.  * BODY->filename actually contains the information.  I'm not sure
  40.  * we want to deal with editing attachments we've already received,
  41.  * so this should be ok.
  42.  *
  43.  * Returns 1 if editor found, 0 if not (useful to tell calling menu to
  44.  * redraw)
  45.  */
  46. int mutt_edit_attachment (BODY *a, int opt)
  47. {
  48.   char type[STRING];
  49.   char command[STRING];
  50.   rfc1524_entry *entry = rfc1524_new_entry ();
  51.  
  52.   snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype);
  53.   if (rfc1524_mailcap_lookup (a, type, entry, M_EDIT))
  54.   {
  55.     if (entry->editcommand)
  56.     {
  57.       char newfile[_POSIX_PATH_MAX] = "";
  58.  
  59.       strfcpy (command, entry->editcommand, sizeof (command));
  60.       if (rfc1524_expand_filename (entry->nametemplate,
  61.                       a->filename, newfile, sizeof (newfile)))
  62.       {
  63.     dprint(1, (debugfile, "oldfile: %s\t newfile: %s\n",
  64.                   a->filename, newfile));
  65.     if (!mutt_rename_file (a->filename, newfile))
  66.     {
  67.       if (!mutt_yesorno ("Can't match nametemplate, continue?", 1))
  68.         return 0;
  69.     }
  70.     else
  71.     {
  72.       safe_free ((void **) &a->filename);
  73.       a->filename = safe_strdup (newfile);
  74.     }
  75.       }
  76.  
  77.       if (rfc1524_expand_command (a, a->filename, type,
  78.                       command, sizeof (command)))
  79.       {
  80.     /* For now, editing requires a file, no piping */
  81.     mutt_error ("Mailcap Edit entry requires %%s");
  82.       }
  83.       else
  84.       {
  85.     endwin ();
  86.     mutt_system (command);
  87.       }
  88.     }
  89.   }
  90.   else if (a->type == TYPETEXT)
  91.   {
  92.     /* On text, default to editor */
  93.     mutt_edit_file (strcmp ("builtin", Editor) == 0 ? Visual : Editor, 
  94.             a->filename);
  95.   }
  96.   else
  97.   {
  98.     rfc1524_free_entry (&entry);
  99.     mutt_error ("No mailcap edit entry for %s",type);
  100.     return 0;
  101.   }
  102.  
  103.   rfc1524_free_entry (&entry);
  104.   return 1;
  105. }
  106.  
  107. int mutt_is_autoview (char *type)
  108. {
  109.   LIST *t = AutoViewList;
  110.   int i;
  111.  
  112.   while (t)
  113.   {
  114.     i = strlen (t->data) - 1;
  115.     if ((i > 0 && t->data[i-1] == '/' && t->data[i] == '*' && 
  116.       strncasecmp (type, t->data, i) == 0) ||
  117.       strcasecmp (type, t->data) == 0)
  118.       return 1;
  119.     t = t->next;
  120.   }
  121.  
  122.   return 0;
  123. }
  124.  
  125. /* returns 0 on error, 1 on success, 2 if we need to toggle OPTWEED */
  126. int mutt_view_attachment (FILE *fp, BODY *a, int flag)
  127. {
  128.   char tempfile[_POSIX_PATH_MAX] = "";
  129.   char pagerfile[_POSIX_PATH_MAX] = "";
  130.   int is_message;
  131.   int use_mailcap;
  132.   int use_pipe = 0;
  133.   int use_pager = 1;
  134.   char type[STRING];
  135.   char command[STRING];
  136.   char descrip[STRING];
  137.   rfc1524_entry *entry = NULL;
  138.   int rc = 0;
  139.  
  140.   is_message = (a->type == TYPEMESSAGE && a->subtype &&
  141.           (!strcasecmp (a->subtype,"rfc822") ||
  142.            !strcasecmp (a->subtype, "news")));
  143.   use_mailcap = (flag == M_MAILCAP ||
  144.         (flag == M_REGULAR && mutt_needs_mailcap (a)));
  145.   snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype);
  146.   
  147.   if (use_mailcap)
  148.   {
  149.     entry = rfc1524_new_entry (); 
  150.     if (!rfc1524_mailcap_lookup (a, type, entry, 0))
  151.     {
  152.       if (flag == M_REGULAR)
  153.       {
  154.     /* fallback to view as text */
  155.     rfc1524_free_entry (&entry);
  156.     mutt_error ("No matching mailcap entry found.  Viewing as text.");
  157.     flag = M_AS_TEXT;
  158.     use_mailcap = 0;
  159.       }
  160.       else
  161.     goto return_error;
  162.     }
  163.   }
  164.   
  165.   if (use_mailcap)
  166.   {
  167.     if (!entry->command)
  168.     {
  169.       mutt_error ("MIME type not defined.  Cannot view attachment.");
  170.       goto return_error;
  171.     }
  172.     strfcpy (command, entry->command, sizeof (command));
  173.     
  174.     if (rfc1524_expand_filename (entry->nametemplate, a->filename,
  175.                     tempfile, sizeof (tempfile)))
  176.     {
  177.       if (fp == NULL)
  178.       {
  179.     /* send case: the file is already there */
  180.     if (!mutt_rename_file (a->filename, tempfile))
  181.     {
  182.       if (mutt_yesorno ("Can't match nametemplate, continue?", 1) == M_YES)
  183.         strfcpy (tempfile, a->filename, sizeof (tempfile));
  184.       else
  185.         goto return_error;
  186.     }
  187.     else
  188.     {
  189.       safe_free ((void **) &a->filename);
  190.       a->filename = safe_strdup (tempfile);
  191.     }
  192.       }
  193.     }
  194.     else if (fp == NULL) /* send case */
  195.       strfcpy (tempfile, a->filename, sizeof (tempfile));
  196.  
  197.     if (fp)
  198.     {
  199.       /* recv case: we need to save the attachment to a file */
  200.       if (mutt_save_attachment (fp, a, tempfile, 0) == -1)
  201.     goto return_error;
  202.     }
  203.  
  204.     use_pipe = rfc1524_expand_command (a, tempfile, type,
  205.                        command, sizeof (command));
  206.     use_pager = entry->copiousoutput;
  207.   }
  208.   
  209.   if (use_pager)
  210.   {
  211.     if (fp && !use_mailcap && a->filename)
  212.     {
  213.       /* recv case */
  214.       strfcpy (pagerfile, a->filename, sizeof (pagerfile));
  215.       mutt_adv_mktemp (pagerfile);
  216.     }
  217.     else
  218.       mutt_mktemp (pagerfile);
  219.   }
  220.     
  221.   if (use_mailcap)
  222.   {
  223.     pid_t thepid = 0;
  224.     FILE *pagerfp = NULL;
  225.     FILE *tempfp = NULL;
  226.     FILE *filter_in;
  227.     FILE *filter_out;
  228.  
  229.     if (!use_pager)
  230.       endwin ();
  231.  
  232.     if (use_pager || use_pipe)
  233.     {
  234.       if (use_pager && ((pagerfp = safe_fopen (pagerfile, "w")) == NULL))
  235.       {
  236.     mutt_perror ("fopen");
  237.     goto return_error;
  238.       }
  239.       if (use_pipe && ((tempfp = fopen (tempfile, "r")) == NULL))
  240.       {
  241.     if (pagerfp)
  242.       fclose (pagerfp);
  243.     mutt_perror ("fopen");
  244.     goto return_error;
  245.       }
  246.  
  247.       if ((thepid = mutt_create_filter (command, use_pipe ? &filter_in : NULL,
  248.               use_pager ? &filter_out : NULL, NULL)) == -1)
  249.       {
  250.     if (pagerfp)
  251.       fclose (pagerfp);
  252.     if (tempfp)
  253.       fclose (tempfp);
  254.     mutt_error ("Cannot create filter");
  255.     goto return_error;
  256.       }
  257.  
  258.       if (use_pipe)
  259.       {
  260.     mutt_copy_stream (tempfp, filter_in);
  261.     fclose (tempfp);
  262.     fclose (filter_in);
  263.       }
  264.       if (use_pager)
  265.       {
  266.     mutt_copy_stream (filter_out, pagerfp);
  267.     fclose (filter_out);
  268.     fclose (pagerfp);
  269.     if (a->description)
  270.       snprintf (descrip, sizeof (descrip),
  271.             "---Command: %-20.20s Description: %s",
  272.             command, a->description);
  273.     else
  274.       snprintf (descrip, sizeof (descrip),
  275.             "---Command: %-30.30s Attachment: %s", command, type);
  276.       }
  277.  
  278.       if ((mutt_wait_filter (thepid) || (entry->needsterminal &&
  279.       option (OPTWAITKEY))) && !use_pager)
  280.     mutt_any_key_to_continue (NULL);
  281.     }
  282.     else
  283.     {
  284.       /* interactive command */
  285.       if (mutt_system (command) || (entry->needsterminal &&
  286.       option (OPTWAITKEY)))
  287.     mutt_any_key_to_continue (NULL);
  288.     }
  289.   }
  290.   else
  291.   {
  292.     /* Don't use mailcap; the attachment is viewed in the pager */
  293.  
  294.     if (flag == M_AS_TEXT)
  295.     {
  296.       /* just let me see the raw data */
  297.       if (mutt_save_attachment (fp, a, pagerfile, 0))
  298.     goto return_error;
  299.     }
  300.     else
  301.     {
  302.       /* Use built-in handler */
  303.       set_option (OPTVIEWATTACH); /* disable the "use 'v' to view this part"
  304.                    * message in case of error */
  305.       if (mutt_decode_save_attachment (fp, a, pagerfile, 1, 0))
  306.       {
  307.     unset_option (OPTVIEWATTACH);
  308.     goto return_error;
  309.       }
  310.       unset_option (OPTVIEWATTACH);
  311.     }
  312.     
  313.     if (a->description)
  314.       strfcpy (descrip, a->description, sizeof (descrip));
  315.     else
  316.       snprintf (descrip, sizeof (descrip), "---Attachment: %s", type);
  317.   }
  318.   
  319.   /* We only reach this point if there have been no errors */
  320.   rc = 1;
  321.  
  322.   if (use_pager)
  323.   {
  324.     /* we have no other way but to do